home *** CD-ROM | disk | FTP | other *** search
- /*****************************************************************************
- * "Irit" - the 3d (not only polygonal) solid modeller. *
- * *
- * Written by: Gershon Elber Ver 0.2, Mar. 1990 *
- ******************************************************************************
- * Module to handle the high level Boolean operations. The other modules *
- * should only call this module to perform Boolean operations. All the *
- * operations are none-destructives, meaning the given data is not modified. *
- * Note all the polygons of the two given objects must be convex, and the *
- * returned object will also have only convex polygons! *
- *****************************************************************************/
-
- /* #define DEBUG2 If defined, defines some printing routines. */
-
- #include <stdio.h>
- #include <ctype.h>
- #include <math.h>
- #include <string.h>
- #include <signal.h>
- #include "irit_sm.h"
- #include "allocate.h"
- #include "attribut.h"
- #include "bool_loc.h"
- #include "convex.h"
- #include "poly_cln.h"
- #include "geomat3d.h"
-
- int BoolHandleCoplanarPoly = FALSE, /* Whether to handle coplanar polys. */
- BoolOutputInterCurve = FALSE; /* Kind of output from Boolean oper. */
-
- static jmp_buf LclLongJumpBuffer; /* Used in fatal Boolean error. */
- static int FatalErrorType; /* Type of fatal Boolean error. */
- static BoolOperType BooleanOperation; /* One of BOOL_OPER_OR, etc. */
-
- static IPObjectStruct *BooleanCombineThreeObjs(IPObjectStruct *PObj1,
- IPObjectStruct *PObj2,
- IPObjectStruct *PObj3);
- static IPObjectStruct *BooleanCoplanar(IPObjectStruct *PObj1,
- IPObjectStruct *PObj2,
- BoolOperType BoolOper);
- static IPObjectStruct *VerifyBooleanInput(IPObjectStruct *PObj1,
- IPObjectStruct *PObj2,
- BoolOperType Oper);
- static IPPolygonStruct *ComputeRotatedPolys(IPPolygonStruct *Pl,
- int CopyPl,
- MatrixType RotMat);
-
- static void BooleanFPE(int Type);
-
- #ifdef DEBUG2
- static void PrintVrtxList(IPVertexStruct *V);
- #endif /* DEBUG2 */
-
- /*****************************************************************************
- * DESCRIPTION: *
- * Verify input for Booleans. Ret. NULL if OK, otherwise an obj to return. *
- * *
- * PARAMETERS: *
- * PObj1: First object for to be performed Boolean. *
- * PObj2: Second object for to be performed Boolean. *
- * Oper: Type of operation (and, or, etc.). *
- * *
- * RETURN VALUE: *
- * IPObjectStruct: NULL if Boolean operation can/should be performed. *
- * Otherwise, an object to return as Boolean result. *
- *****************************************************************************/
- static IPObjectStruct *VerifyBooleanInput(IPObjectStruct *PObj1,
- IPObjectStruct *PObj2,
- BoolOperType Oper)
- {
- IPObjectStruct *PObj;
- IPPolygonStruct *Pl;
-
- BooleanOperation = Oper;
-
- if (!IP_IS_POLY_OBJ(PObj1) || (PObj2 != NULL && !IP_IS_POLY_OBJ(PObj2)))
- IritFatalError("Boolean: operation on non polygonal object(s).");
-
- signal(SIGFPE, BooleanFPE); /* Will trap floating point errors. */
-
- switch (Oper) {
- case BOOL_OPER_OR:
- if (IP_IS_POLYLINE_OBJ(PObj1) && IP_IS_POLYLINE_OBJ(PObj2)) {
- if (PObj1 -> U.Pl == NULL)
- PObj = CopyObject(NULL, PObj2, FALSE);
- else {
- PObj = CopyObject(NULL, PObj1, FALSE);
- Pl = IritPrsrGetLastPoly(PObj -> U.Pl);
- Pl -> Pnext = CopyPolygonList(PObj2 -> U.Pl);
- }
- return PObj;
- }
- case BOOL_OPER_AND:
- case BOOL_OPER_SUB:
- case BOOL_OPER_CUT:
- case BOOL_OPER_MERGE:
- case BOOL_OPER_NEG:
- if (IP_IS_POLYLINE_OBJ(PObj1) ||
- (PObj2 != NULL && IP_IS_POLYLINE_OBJ(PObj2))) {
- IritWarningError(
- "Boolean: illegal operation on mixed polygon/line geometric object(s).");
- PObj = GenPolyObject("", NULL, NULL);
- return PObj;
- }
-
- if (Oper != BOOL_OPER_NEG) {
- ConvexPolyObject(PObj1);/* Make sure all polygons are convex.*/
- ConvexPolyObject(PObj2);
- }
-
- return NULL;
- default:
- IritFatalError("Boolean: undefined Boolean operation.");
- return NULL; /* Make warning silent. */
- }
- }
-
- /*****************************************************************************
- * DESCRIPTION: M
- * Performs a Boolean OR between two objects. M
- * *
- * PARAMETERS: M
- * PObj1: First object to perform the Boolean operation on. M
- * PObj2: Second object to perform the Boolean operation on. M
- * *
- * RETURN VALUE: M
- * IPObjectStruct: The result of the Boolean operation. M
- * *
- * KEYWORDS: M
- * BooleanOR, Booleans M
- *****************************************************************************/
- IPObjectStruct *BooleanOR(IPObjectStruct *PObj1, IPObjectStruct *PObj2)
- {
- IPObjectStruct *PObj;
- IPPolygonStruct *Pl;
-
- if ((PObj = VerifyBooleanInput(PObj1, PObj2, BOOL_OPER_OR)) != NULL)
- return PObj;
- else {
- if (setjmp(LclLongJumpBuffer) == 0) { /* Its the setjmp itself call! */
- signal(SIGFPE, BooleanFPE); /* Will trap floating point errors. */
- if (BoolOutputInterCurve)
- PObj = BooleanLow1Out2(PObj1, PObj2);/* Ret intersection crv.*/
- else
- PObj = BooleanCombineThreeObjs(BooleanLow1Out2(PObj1, PObj2),
- BooleanLow1Out2(PObj2, PObj1),
- BooleanCoplanar(PObj1, PObj2,
- BOOL_OPER_OR));
-
- }
- else {
- /* We gain control from fatal error long jump - usually we should*/
- /* return empty object, but if error is no intersection between */
- /* the two objects, we assume they have no common volume and */
- /* return a new object consists of the concat. of all polygons! */
- if (FatalErrorType != FTL_BOOL_NO_INTER) {
- PObj = GenPolyObject("", NULL, NULL);/* Return empty object. */
- }
- else {
- if (PObj1 -> U.Pl == NULL)
- PObj = CopyObject(NULL, PObj2, FALSE);
- else {
- PObj = CopyObject(NULL, PObj1, FALSE);/* Copy Obj1 polys.*/
- Pl = PObj -> U.Pl;
- while (Pl -> Pnext) Pl = Pl -> Pnext;
- Pl -> Pnext = CopyPolygonList(PObj2 -> U.Pl);/*Obj2 poly.*/
- }
- }
- }
- }
-
- return PObj;
- }
-
- /*****************************************************************************
- * DESCRIPTION: M
- * Performs a Boolean AND between two objects. M
- * *
- * PARAMETERS: M
- * PObj1: First object to perform the Boolean operation on. M
- * PObj2: Second object to perform the Boolean operation on. M
- * *
- * RETURN VALUE: M
- * IPObjectStruct: The result of the Boolean operation. M
- * *
- * KEYWORDS: M
- * BooleanAND, Booleans M
- *****************************************************************************/
- IPObjectStruct *BooleanAND(IPObjectStruct *PObj1, IPObjectStruct *PObj2)
- {
- IPObjectStruct *PObj;
-
- if ((PObj = VerifyBooleanInput(PObj1, PObj2, BOOL_OPER_AND)) != NULL)
- return PObj;
- else {
- if (setjmp(LclLongJumpBuffer) == 0) { /* Its the setjmp itself call! */
- signal(SIGFPE, BooleanFPE); /* Will trap floating point errors. */
- if (BoolOutputInterCurve)
- PObj = BooleanLow1In2(PObj1, PObj2);/* Ret intersection crv. */
- else
- PObj = BooleanCombineThreeObjs(BooleanLow1In2(PObj1, PObj2),
- BooleanLow1In2(PObj2, PObj1),
- BooleanCoplanar(PObj1, PObj2,
- BOOL_OPER_AND));
-
- }
- else {/* We gain control from fatal error long jump - ret empty obj. */
- PObj = GenPolyObject("", NULL, NULL);
- }
- }
-
- return PObj;
- }
-
- /*****************************************************************************
- * DESCRIPTION: M
- * Performs a Boolean SUBtracion between two objects. M
- * *
- * PARAMETERS: M
- * PObj1: First object to perform the Boolean operation on. M
- * PObj2: Second object to perform the Boolean operation on. M
- * *
- * RETURN VALUE: M
- * IPObjectStruct: The result of the Boolean operation. M
- * *
- * KEYWORDS: M
- * BooleanSUB, Booleans M
- *****************************************************************************/
- IPObjectStruct *BooleanSUB(IPObjectStruct *PObj1, IPObjectStruct *PObj2)
- {
- IPObjectStruct *PObj, *PTemp, *PTempRev;
-
- if ((PObj = VerifyBooleanInput(PObj1, PObj2, BOOL_OPER_SUB)) != NULL)
- return PObj;
- else {
- if (setjmp(LclLongJumpBuffer) == 0) { /* Its the setjmp itself call! */
- signal(SIGFPE, BooleanFPE); /* Will trap floating point errors. */
- /* The 1 in 2 must be reversed (the inside/outside orientation): */
- if (BoolOutputInterCurve) {
- PObj = BooleanLow1In2(PObj2, PObj1);/* Ret intersection crv. */
- }
- else {
- PTemp = BooleanLow1In2(PObj2, PObj1);
- PTempRev = BooleanNEG(PTemp);
- IPFreeObject(PTemp);
-
- PObj = BooleanCombineThreeObjs(BooleanLow1Out2(PObj1, PObj2),
- PTempRev,
- BooleanCoplanar(PObj1, PObj2,
- BOOL_OPER_SUB));
- }
- }
- else {/* We gain control from fatal error long jump - ret empty obj. */
- PObj = GenPolyObject("", NULL, NULL);
- }
- }
-
- return PObj;
- }
-
- /*****************************************************************************
- * DESCRIPTION: M
- * Performs a Boolean CUT between two objects. M
- * *
- * PARAMETERS: M
- * PObj1: First object to perform the Boolean operation on. M
- * PObj2: Second object to perform the Boolean operation on. M
- * *
- * RETURN VALUE: M
- * IPObjectStruct: The result of the Boolean operation. M
- * *
- * KEYWORDS: M
- * BooleanCUT, Booleans M
- *****************************************************************************/
- IPObjectStruct *BooleanCUT(IPObjectStruct *PObj1, IPObjectStruct *PObj2)
- {
- IPObjectStruct *PObj;
-
- if ((PObj = VerifyBooleanInput(PObj1, PObj2, BOOL_OPER_CUT)) != NULL)
- return PObj;
- else {
- if (setjmp(LclLongJumpBuffer) == 0) { /* Its the setjmp itself call! */
- signal(SIGFPE, BooleanFPE); /* Will trap floating point errors. */
- /* The 1 in 2 must be reversed (the inside/outside orientation): */
- if (BoolOutputInterCurve) {
- PObj = BooleanLow1In2(PObj2, PObj1);/* Ret intersection crv. */
- }
- else {
- PObj = BooleanLow1Out2(PObj1, PObj2);
- }
- }
- else {/* We gain control from fatal error long jump - ret empty obj. */
- PObj = GenPolyObject("", NULL, NULL);
- }
- }
-
- return PObj;
- }
-
- /*****************************************************************************
- * DESCRIPTION: M
- * Performs a Boolean Inside CUT between two objects. M
- * *
- * PARAMETERS: M
- * PObj1: First object to perform the Boolean operation on. M
- * PObj2: Second object to perform the Boolean operation on. M
- * *
- * RETURN VALUE: M
- * IPObjectStruct: The result of the Boolean operation. M
- * *
- * KEYWORDS: M
- * BooleanICUT, Booleans M
- *****************************************************************************/
- IPObjectStruct *BooleanICUT(IPObjectStruct *PObj1, IPObjectStruct *PObj2)
- {
- IPObjectStruct *PObj;
-
- if ((PObj = VerifyBooleanInput(PObj1, PObj2, BOOL_OPER_CUT)) != NULL)
- return PObj;
- else {
- if (setjmp(LclLongJumpBuffer) == 0) { /* Its the setjmp itself call! */
- signal(SIGFPE, BooleanFPE); /* Will trap floating point errors. */
- /* The 1 in 2 must be reversed (the inside/outside orientation): */
- if (BoolOutputInterCurve) {
- PObj = BooleanLow1In2(PObj2, PObj1);/* Ret intersection crv. */
- }
- else {
- PObj = BooleanLow1In2(PObj1, PObj2);
- }
- }
- else {/* We gain control from fatal error long jump - ret empty obj. */
- PObj = GenPolyObject("", NULL, NULL);
- }
- }
-
- return PObj;
- }
-
- /*****************************************************************************
- * DESCRIPTION: M
- * Performs a Boolean MERGE between two objects. M
- * *
- * PARAMETERS: M
- * PObj1: First object to perform the Boolean operation on. M
- * PObj2: Second object to perform the Boolean operation on. M
- * *
- * RETURN VALUE: M
- * IPObjectStruct: The result of the Boolean operation. M
- * *
- * KEYWORDS: M
- * BooleanMERGE, Booleans M
- *****************************************************************************/
- IPObjectStruct *BooleanMERGE(IPObjectStruct *PObj1, IPObjectStruct *PObj2)
- {
- IPObjectStruct *PObj;
- IPPolygonStruct *Pl;
-
- if ((PObj = VerifyBooleanInput(PObj1, PObj2, BOOL_OPER_MERGE)) != NULL)
- return PObj;
- else {
- if (PObj1 -> U.Pl == NULL)
- PObj = CopyObject(NULL, PObj2, FALSE);
- else {
- PObj = CopyObject(NULL, PObj1, FALSE); /* Copy Obj1 polys. */
- Pl = PObj -> U.Pl;
- while (Pl -> Pnext) Pl = Pl -> Pnext;
- Pl -> Pnext = CopyPolygonList(PObj2 -> U.Pl); /* Obj2 polys. */
- }
- }
-
- return PObj;
- }
-
- /*****************************************************************************
- * DESCRIPTION: M
- * Performs a Boolean NEG between two objects. M
- * Negation is simply reversing the direction of the plane equation of each M
- * polygon - the simplest Boolean operation... M
- * *
- * PARAMETERS: M
- * PObj: Object to negate. M
- * *
- * RETURN VALUE: M
- * IPObjectStruct: The result of the Boolean operation. M
- * *
- * KEYWORDS: M
- * BooleanNEG, Booleans M
- *****************************************************************************/
- IPObjectStruct *BooleanNEG(IPObjectStruct *PObj)
- {
- int i;
- IPObjectStruct *PTemp;
- IPPolygonStruct *Pl;
- IPVertexStruct *V;
-
- if ((PTemp = VerifyBooleanInput(PObj, NULL, BOOL_OPER_NEG)) != NULL)
- return PTemp;
- else {
- PTemp = CopyObject(NULL, PObj, FALSE); /* Make fresh copy of object. */
-
- /* Scans all polygons and reverse plane equation and their vetrex */
- /* list (cross prod. of consecutive edges must be in normal dir.). */
- Pl = PTemp -> U.Pl;
- while (Pl != NULL) {
- for (i = 0; i < 4; i++)
- Pl -> Plane[i] = (-Pl -> Plane[i]);
- IP_RST_CONVEX_POLY(Pl);
-
- /* Invert vertices normals as well. */
- V = Pl -> PVertex;
- do {
- PT_SCALE(V -> Normal, -1.0);
- V = V -> Pnext;
- }
- while (V != NULL && V != Pl -> PVertex);
-
- /* And reverse the order of the vertices. */
- IritPrsrReverseVrtxList(Pl);
-
- Pl = Pl -> Pnext;
- }
- }
-
- return PTemp;
- }
-
- /*****************************************************************************
- * DESCRIPTION: *
- * Combining three geometric objects, by simply concat. their polygon. *
- * lists. Any object may be NULL in which only the other two are merged. *
- * *
- * PARAMETERS: *
- * PObj1, PObj2, PObj3: The three objects to concatenate. *
- * *
- * RETURN VALUE: *
- * IPObjectStruct: Concatenated object. *
- *****************************************************************************/
- static IPObjectStruct *BooleanCombineThreeObjs(IPObjectStruct *PObj1,
- IPObjectStruct *PObj2,
- IPObjectStruct *PObj3)
- {
- IPPolygonStruct *Pl;
-
- if (PObj1 != NULL) {
- CleanUpPolygonList(&PObj1 -> U.Pl);
- if (PObj1 -> U.Pl == NULL) {
- IPFreeObject(PObj1);
- PObj1 = NULL;
- }
- }
- if (PObj2 != NULL) {
- CleanUpPolygonList(&PObj2 -> U.Pl);
- if (PObj2 -> U.Pl == NULL) {
- IPFreeObject(PObj2);
- PObj2 = NULL;
- }
- }
- if (PObj3 != NULL) {
- CleanUpPolygonList(&PObj3 -> U.Pl);
- if (PObj3 -> U.Pl == NULL) {
- IPFreeObject(PObj3);
- PObj3 = NULL;
- }
- }
-
- if (PObj1 == NULL) {
- PObj1 = PObj2;
- PObj2 = PObj3;
- PObj3 = NULL;
- }
- if (PObj2 == NULL) {
- PObj2 = PObj3;
- PObj3 = NULL;
- }
-
- if (PObj2 != NULL) {
- /* Concat the polygons of PObj2 after the polygons of PObj1. */
- Pl = PObj1 -> U.Pl;
- while (Pl -> Pnext != NULL)
- Pl = Pl -> Pnext;
- Pl -> Pnext = PObj2 -> U.Pl; /* Concat. the polygons into one list. */
- PObj2 -> U.Pl = NULL; /* And release the second object header. */
- IPFreeObject(PObj2);
-
- if (PObj3 != NULL) {
- /* Concat the polygons of PObj3 after the polygons of PObj1/2. */
- while (Pl -> Pnext != NULL)
- Pl = Pl -> Pnext;
- Pl -> Pnext = PObj3 -> U.Pl; /* Concat. polygons into one list. */
- PObj3 -> U.Pl = NULL; /* And release the second object header. */
- IPFreeObject(PObj3);
- }
- }
-
- return PObj1;
- }
-
- /*****************************************************************************
- * DESCRIPTION: *
- * If required (I.e. Object "COPLANAR" is set to TRUE) search all coplanar *
- * polygons in PObj1/2 and invoke the necessary two dimenstional Boolean. *
- * *
- * PARAMETERS: *
- * PObj1, PObj2: Two objects to search for coplanar polygons. *
- * BoolOper: Type of Boolean operation to be performed between PObj1/2. *
- * *
- * RETURN VALUE: *
- * IPObjectStruct: The resulting Boolean operation. *
- *****************************************************************************/
- static IPObjectStruct *BooleanCoplanar(IPObjectStruct *PObj1,
- IPObjectStruct *PObj2,
- BoolOperType BoolOper)
- {
- MatrixType RotMat;
- IPObjectStruct *PObj;
- IPPolygonStruct *Pl, *PlTmp, *Pl1, *Pl2, *Pl1XY, *Pl2XY, *Pl1XYR, *Pl2XYR,
- *PlOut = NULL;
-
- if (!BoolHandleCoplanarPoly)
- return NULL;
-
- for ( Pl1 = PObj1 -> U.Pl; Pl1 != NULL; Pl1 = Pl1 -> Pnext) {
- for ( Pl2 = PObj2 -> U.Pl; Pl2 != NULL; Pl2 = Pl2 -> Pnext) {
- RealType
- *Plane1 = Pl1 -> Plane,
- *Plane2 = Pl2 -> Plane;
- int Shared = BOOL_APX_EQ(Plane1[0], Plane2[0]) &&
- BOOL_APX_EQ(Plane1[1], Plane2[1]) &&
- BOOL_APX_EQ(Plane1[2], Plane2[2]) &&
- BOOL_APX_EQ(Plane1[3], Plane2[3]),
- AntiShared = BOOL_APX_EQ(Plane1[0], -Plane2[0]) &&
- BOOL_APX_EQ(Plane1[1], -Plane2[1]) &&
- BOOL_APX_EQ(Plane1[2], -Plane2[2]) &&
- BOOL_APX_EQ(Plane1[3], -Plane2[3]);
-
- if (!Shared && !AntiShared) {
- /* The two polygons are not coplanar, do not intersect. */
- continue;
- }
-
- if (Shared) {
- switch (BoolOper) {
- case BOOL_OPER_AND:
- case BOOL_OPER_OR:
- case BOOL_OPER_SUB:
- GenRotateMatrix(RotMat, Pl1 -> Plane);
- Pl1XY = ComputeRotatedPolys(Pl1, TRUE, RotMat);
- Pl2XY = ComputeRotatedPolys(Pl2, TRUE, RotMat);
- /* Find the inverse matrix. */
- if (!MatInverseMatrix(RotMat, RotMat))
- IritFatalError("BooleanCoplanar: Inverse matrix does not exists");
-
- if ((Pl = Boolean2D(Pl1XY, Pl2XY, BoolOper)) != NULL) {
- Pl = ComputeRotatedPolys(Pl, FALSE, RotMat);
- for (PlTmp = Pl;
- PlTmp -> Pnext != NULL;
- PlTmp = PlTmp -> Pnext);
- PlTmp -> Pnext = PlOut;
- PlOut = Pl;
- }
-
- IPFreePolygonList(Pl1XY);
- IPFreePolygonList(Pl2XY);
- break;
-
- default:
- IritFatalError("BooleanCoplanar: Unsupported Boolean operation BooleanCoplanar");
- return NULL;
- }
- }
- else if (AntiShared) {
- switch (BoolOper) {
- case BOOL_OPER_AND:
- case BOOL_OPER_SUB:
- IritWarningError("Antishared coplanar polygons are ignored.");
- break;
-
- case BOOL_OPER_OR:
- GenRotateMatrix(RotMat, Pl1 -> Plane);
- Pl1XY = ComputeRotatedPolys(Pl1, TRUE, RotMat);
- Pl1XYR = CopyPolygonList(Pl1XY);
- IritPrsrReverseVrtxList(Pl1XYR);
- Pl2XY = ComputeRotatedPolys(Pl2, TRUE, RotMat);
- Pl2XYR = CopyPolygonList(Pl2XY);
- IritPrsrReverseVrtxList(Pl2XYR);
-
- if (!MatInverseMatrix(RotMat, RotMat))
- IritFatalError("BooleanCoplanar: Inverse matrix does not exists");
-
- if ((Pl = Boolean2D(Pl1XY, Pl2XYR, BOOL_OPER_SUB)) != NULL) {
- Pl = ComputeRotatedPolys(Pl, FALSE, RotMat);
- for (PlTmp = Pl;
- PlTmp -> Pnext != NULL;
- PlTmp = PlTmp -> Pnext);
- PlTmp -> Pnext = PlOut;
- PlOut = Pl;
- }
- if ((Pl = Boolean2D(Pl2XY, Pl1XYR, BOOL_OPER_SUB)) != NULL) {
- Pl = ComputeRotatedPolys(Pl, FALSE, RotMat);
- for (PlTmp = Pl;
- PlTmp -> Pnext != NULL;
- PlTmp = PlTmp -> Pnext);
- PlTmp -> Pnext = PlOut;
- PlOut = Pl;
- }
-
- IPFreePolygonList(Pl1XY);
- IPFreePolygonList(Pl2XY);
- IPFreePolygonList(Pl1XYR);
- IPFreePolygonList(Pl2XYR);
- break;
-
- default:
- IritFatalError("BooleanCoplanar: Unsupported Boolean operation BooleanCoplanar");
- return NULL;
- }
- }
- }
- }
-
- PObj = IPAllocObject("", IP_OBJ_POLY, NULL);
- PObj -> U.Pl = PlOut;
- return PObj;
- }
-
- /*****************************************************************************
- * DESCRIPTION: *
- * Routine to optionally copy (if CpolyOnePl) a single polygon and rotate *
- * according to the rotation matrix provided. If, however, CopyOnePl is False *
- * all polygons in list are converted. *
- * *
- * PARAMETERS: *
- * Pl: Polygon(s) to transform. *
- * CopyOnePl: Should we copy? *
- * RotMat: Transformation matrix. *
- * *
- * RETURN VALUE: *
- * IPPolygonStruct: Transformed polygon(s). *
- *****************************************************************************/
- static IPPolygonStruct *ComputeRotatedPolys(IPPolygonStruct *Pl,
- int CopyOnePl,
- MatrixType RotMat)
- {
- IPVertexStruct *V, *VHead;
- IPPolygonStruct *PlNext, *PlTemp,
- *PlOut = NULL;
-
- while (Pl != NULL) {
- PlNext = Pl -> Pnext;
-
- if (CopyOnePl) {
- PlTemp = IPAllocPolygon(Pl -> Count, Pl -> Tags,
- CopyVertexList(Pl -> PVertex), NULL);
- PLANE_COPY(PlTemp ->Plane, Pl -> Plane);
- Pl = PlTemp;
- }
-
- V = VHead = Pl -> PVertex;
- do { /* Transform the polygon itself. */
- PointType PTemp;
-
- PT_ADD(PTemp, V -> Coord, V -> Normal);
-
- MatMultVecby4by4(V -> Coord, V -> Coord, RotMat);
-
- MatMultVecby4by4(PTemp, PTemp, RotMat); /* Update normal. */
- PT_SUB(V -> Normal, PTemp, V -> Coord);
- PT_NORMALIZE(V -> Normal);
-
- V = V -> Pnext;
- }
- while (V != NULL && V != VHead);
-
- Pl -> Pnext = PlOut;
- PlOut = Pl;
-
- if (CopyOnePl)
- break;
- else
- Pl = PlNext;
- }
-
- return PlOut;
- }
-
- /*****************************************************************************
- * DESCRIPTION: *
- * Routine that is called from the floating point package in case of fatal *
- * floating point error. Print error message, and quit the Boolean module. *
- * *
- * PARAMETERS: *
- * Type: of exception. *
- * *
- * RETURN VALUE: *
- * void *
- *****************************************************************************/
- static void BooleanFPE(int Type)
- {
- char Line[LINE_LEN];
-
- sprintf(Line, "Floating point error %d.", Type);
- IritWarningError(Line);
-
- FatalErrorType = FTL_BOOL_FPE;
-
- longjmp(LclLongJumpBuffer, 1);
- }
-
- /*****************************************************************************
- * DESCRIPTION: M
- * Controls if intersection curves or full Boolean operation is to be M
- * performed. M
- * *
- * PARAMETERS: M
- * OutputInterCurve: If TRUE only intersection curves are computed, If M
- * false, full blown Boolean is applied. M
- * *
- * RETURN VALUE: M
- * void M
- * *
- * KEYWORDS: M
- * BoolSetOutputInterCurve, Booleans M
- *****************************************************************************/
- void BoolSetOutputInterCurve(int OutputInterCurve)
- {
- BoolOutputInterCurve = OutputInterCurve;
- }
-
- /*****************************************************************************
- * DESCRIPTION: M
- * Controls if coplanar polygons should be handled or not. M
- * *
- * PARAMETERS: M
- * HandleCoplanarPoly: If TRUE, coplanar polygons are handled. M
- * *
- * RETURN VALUE: M
- * void M
- * *
- * KEYWORDS: M
- * BoolSetHandleCoplanarPoly, Booleans M
- *****************************************************************************/
- void BoolSetHandleCoplanarPoly(int HandleCoplanarPoly)
- {
- BoolHandleCoplanarPoly = HandleCoplanarPoly;
- }
-
- /*****************************************************************************
- * DESCRIPTION: *
- * Routine that is called by the bool-low module in fatal error cases. *
- * Will print error message and long jump using LclLongJumpBuffer. *
- * *
- * PARAMETERS: *
- * ErrorType: Type of error. *
- * *
- * RETURN VALUE: *
- * void *
- *****************************************************************************/
- void FatalBooleanError(int ErrorType)
- {
- char s[LINE_LEN_LONG];
-
- FatalErrorType = ErrorType;
-
- switch (ErrorType) {
- case FTL_BOOL_NO_INTER:
- /* If operation is union (OR), then if no intersection we assume */
- /* the objects have no common volume and simply combine them! */
- if (BooleanOperation != BOOL_OPER_OR) {
- sprintf(s, "Boolean: %s",
- "Objects do not intersect - Empty object result");
- IritWarningError(s);
- }
- break;
- default:
- sprintf(s, "Boolean: Undefined Fatal Error (%d !?)", ErrorType);
- IritWarningError(s);
- break;
- }
-
- longjmp(LclLongJumpBuffer, 1);
- }
-
- #ifdef DEBUG2
-
- /*****************************************************************************
- * DESCRIPTION: *
- * Prints the content of the given vertex list, to standard output. *
- * *
- * PARAMETERS: *
- * V: Vertex list to print. *
- * *
- * RETURN VALUE: *
- * void *
- *****************************************************************************/
- static void PrintVrtxList(IPVertexStruct *V)
- {
- IPVertexStruct
- *VHead = V;
-
- do {
- printf("[NORMAL %8lf %8lf %8lf] %12lf %12lf %12lf",
- V -> Normal[0], V -> Normal[1], V -> Normal[2],
- V -> Coord[0], V -> Coord[1], V -> Coord[2]);
- if (IP_IS_INTERNAL_EDGE(V))
- printf(" (Internal)\n");
- else
- printf("\n");
- V = V -> Pnext;
- }
- while (V!= NULL && V != VHead);
- }
-
- #endif /* DEBUG2 */
-